home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / enscript.4 / enscript / enscript-1.4.0 / afmlib / afm.c next >
Encoding:
C/C++ Source or Header  |  1996-05-24  |  19.4 KB  |  846 lines

  1. /* 
  2.  * AFM library public interface.
  3.  * Copyright (c) 1995 Markku Rossi.
  4.  *
  5.  * Author: Markku Rossi <mtr@iki.fi>
  6.  */
  7.  
  8. /*
  9.  * This file is part of the AFM library.
  10.  * 
  11.  * This library is free software; you can redistribute it and/or
  12.  * modify it under the terms of the GNU Library General Public
  13.  * License as published by the Free Software Foundation; either
  14.  * version 2 of the License, or (at your option) any later version.
  15.  *
  16.  * This library is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19.  * Library General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU Library General Public
  22.  * License along with this library; if not, write to the Free
  23.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "afmint.h"
  27. #include "afm.h"
  28.  
  29. /*
  30.  * Static variables
  31.  */
  32.  
  33. static char *default_path = "/usr/local/lib/ps:/usr/lib/ps";
  34.  
  35. static char *error_names[] =
  36. {
  37.   "AFM Success",
  38.   "AFM Error",
  39.   "out of memory",
  40.   "illegal argument",
  41.   "unknown font",
  42.   "syntax error",
  43.   "unsupported format",
  44.   "file IO failed",
  45.   "file is not an AFM file",
  46. };
  47.  
  48. /*
  49.  * Prototypes for static functions.
  50.  */
  51.  
  52. static void read_font_map __P ((AFMHandle handle, char *name));
  53. static void apply_encoding __P ((AFMFont font, AFMEncodingTable *enc,
  54.                  unsigned int flags));
  55.  
  56.  
  57. /*
  58.  * Global functions.
  59.  */
  60.  
  61. void
  62. afm_error_to_string (AFMError error, char *buf)
  63. {
  64.   char *syserr;
  65.   int code, syserrno;
  66.  
  67.   code = error & 0xffff;
  68.   syserrno = (error >> 16) & 0xffff;
  69.  
  70.   if (syserrno)
  71.     syserr = strerror (syserrno);
  72.   else
  73.     syserr = NULL;
  74.  
  75.   if (code >= NUM_ERRORS)
  76.     {
  77.       sprintf (buf, "afm_error_to_string(): illegal error code: %d\n",
  78.            error);
  79.       return;
  80.     }
  81.  
  82.   if (code == 0)
  83.     sprintf (buf, "AFM Success");
  84.   else if (code == 1)
  85.     sprintf (buf, "%s%s%s", "AFM Error",
  86.          syserr ? ":" : "",
  87.          syserr ? syserr : "");
  88.   else
  89.     sprintf (buf, "AFM Error: %s%s%s", error_names[code],
  90.          syserr ? ": " : "",
  91.          syserr ? syserr : "");
  92. }
  93.  
  94.  
  95. AFMError
  96. afm_create (const char *path, unsigned int verbose_level,
  97.         AFMHandle *handle_return)
  98. {
  99.   AFMHandle handle;
  100.   AFMError error = AFM_SUCCESS;
  101.   const char *cp, *cp2;
  102.   int len;
  103.   char buf[512];
  104.   struct stat stat_st;
  105.  
  106.   /* Init handle. */
  107.  
  108.   handle = (AFMHandle) calloc (1, sizeof (*handle));
  109.   if (handle == NULL)
  110.     {
  111.       error = AFM_ERROR_MEMORY;
  112.       goto error_out;
  113.     }
  114.  
  115.   handle->font_map = strhash_init ();
  116.   if (handle->font_map == NULL)
  117.     {
  118.       error = AFM_ERROR_MEMORY;
  119.       goto error_out;
  120.     }
  121.  
  122.   handle->verbose = verbose_level;
  123.  
  124.   /* Traverse path. */
  125.  
  126.   if (path == NULL)
  127.     path = default_path;
  128.  
  129.   afm_message (handle, 1, "AFM: scanning path...\n");
  130.   for (cp = path; cp; cp = strchr (cp, PATH_SEPARATOR))
  131.     {
  132.       if (cp != path)
  133.     cp++;
  134.  
  135.       cp2 = strchr (cp, PATH_SEPARATOR);
  136.       if (cp2)
  137.     len = cp2 - cp;
  138.       else
  139.     len = strlen (cp);
  140.  
  141.       memcpy (buf, cp, len);
  142.       buf[len] = '\0';
  143.       if (len > 0 && buf[len - 1] == '/')
  144.     buf[len - 1] = '\0';
  145.  
  146.       strcat (buf, "/font.map");
  147.  
  148.       if (stat (buf, &stat_st) == 0)
  149.     read_font_map (handle, buf);
  150.     }
  151.  
  152.   *handle_return = handle;
  153.  
  154.   return AFM_SUCCESS;
  155.  
  156.  
  157.   /* Error handling. */
  158.  
  159.  error_out:
  160.  
  161.   (void) afm_destroy (handle);
  162.  
  163.   return error;
  164. }
  165.  
  166.  
  167. AFMError
  168. afm_destroy (AFMHandle handle)
  169. {
  170.   char *key;
  171.   int keylen;
  172.   char *cp;
  173.  
  174.   if (handle == NULL)
  175.     return AFM_ERROR_ARGUMENT;
  176.  
  177.   /* Free filenames. */
  178.   while (strhash_get_first (handle->font_map, &key, &keylen, (void *) &cp))
  179.     free (cp);
  180.  
  181.   strhash_free (handle->font_map);
  182.   free (handle);
  183.  
  184.   return AFM_SUCCESS;
  185. }
  186.  
  187.  
  188. AFMError
  189. afm_set_verbose (AFMHandle handle, unsigned int level)
  190. {
  191.   if (handle == NULL)
  192.     return AFM_ERROR_ARGUMENT;
  193.  
  194.   handle->verbose = level;
  195.  
  196.   return AFM_SUCCESS;
  197. }
  198.  
  199.  
  200. AFMError
  201. afm_font_prefix (AFMHandle handle, const char *fontname,
  202.          const char **prefix_return)
  203. {
  204.   char *filename;
  205.  
  206.   if (handle == NULL || fontname == NULL || prefix_return == NULL)
  207.     return AFM_ERROR_ARGUMENT;
  208.  
  209.   /* Lookup font. */
  210.   if (!strhash_get (handle->font_map, fontname, strlen (fontname),
  211.             (void *) &filename))
  212.     return AFM_ERROR_UNKNOWN_FONT;
  213.  
  214.   *prefix_return = filename;
  215.  
  216.   return AFM_SUCCESS;
  217. }
  218.  
  219.  
  220. AFMError
  221. afm_open_font (AFMHandle handle, unsigned int info_level,
  222.            const char *fontname, AFMFont *font_return)
  223. {
  224.   char *filename;
  225.   char fname[512];
  226.  
  227.   if (handle == NULL || fontname == NULL)
  228.     return AFM_ERROR_ARGUMENT;
  229.  
  230.   /* Lookup font. */
  231.   if (!strhash_get (handle->font_map, fontname, strlen (fontname),
  232.             (void *) &filename))
  233.     return AFM_ERROR_UNKNOWN_FONT;
  234.  
  235.   /* Append suffix to the filename. */
  236.   sprintf (fname, "%s.afm", filename);
  237.  
  238.   return afm_open_file (handle, info_level, fname, font_return);
  239. }
  240.  
  241.  
  242. AFMError
  243. afm_open_file (AFMHandle handle, unsigned int info_level,
  244.            const char *filename, AFMFont *font_return)
  245. {
  246.   AFMFont font;
  247.   AFMError error = AFM_SUCCESS;
  248.   
  249.   if (handle == NULL || filename == NULL)
  250.     return AFM_ERROR_ARGUMENT;
  251.  
  252.   font = (AFMFont) calloc (1, sizeof (*font));
  253.   if (font == NULL)
  254.     return AFM_ERROR_MEMORY;
  255.  
  256.   font->private
  257.     = (struct afm_font_private_data_st *) calloc (1, sizeof (*font->private));
  258.   if (font->private == NULL)
  259.     {
  260.       error = AFM_ERROR_MEMORY;
  261.       goto error_out;
  262.     }
  263.   font->private->fontnames = strhash_init ();
  264.   if (font->private->fontnames == NULL)
  265.     {
  266.       error = AFM_ERROR_MEMORY;
  267.       goto error_out;
  268.     }
  269.  
  270.   font->private->compositenames = strhash_init ();
  271.   if (font->private->compositenames == NULL)
  272.     {
  273.       error = AFM_ERROR_MEMORY;
  274.       goto error_out;
  275.     }
  276.  
  277.   font->info_level = info_level;
  278.  
  279.   /* Parse file. */
  280.   if (setjmp (handle->jmpbuf))
  281.     {
  282.       /* Error during parse. */
  283.       error = handle->parse_error;
  284.       goto error_out;
  285.     }
  286.   else
  287.     {
  288.       afm_parse_file (handle, filename, font);
  289.       /* Parse successful. */
  290.     }
  291.  
  292.   *font_return = font;
  293.   return AFM_SUCCESS;
  294.  
  295.  
  296.   /* Error handling. */
  297.  
  298.  error_out:
  299.  
  300.   (void) afm_close_font (font);
  301.  
  302.   return error;
  303. }
  304.  
  305.  
  306. #define FREE(ptr) if (ptr) free (ptr)
  307. AFMError
  308. afm_close_font (AFMFont font)
  309. {
  310.   int i;
  311.  
  312.   if (font == NULL)
  313.     return AFM_ERROR_ARGUMENT;
  314.  
  315.   /* Global info. */
  316.   FREE (font->global_info.FontName);
  317.   FREE (font->global_info.FullName);
  318.   FREE (font->global_info.FamilyName);
  319.   FREE (font->global_info.Weight);
  320.   FREE (font->global_info.Version);
  321.   FREE (font->global_info.Notice);
  322.   FREE (font->global_info.EncodingScheme);
  323.   FREE (font->global_info.CharacterSet);
  324.  
  325.   /* Character metrics. */
  326.   for (i = 0; i < font->num_character_metrics; i++)
  327.     FREE (font->character_metrics[i].name);
  328.   FREE (font->character_metrics);
  329.  
  330.   /* Composites. */
  331.   for (i = 0; i < font->num_composites; i++)
  332.     FREE (font->composites[i].name);
  333.   FREE (font->composites);
  334.  
  335.   /* Kern pairs. */
  336.   for (i = 0; i < font->num_kern_pairs; i++)
  337.     {
  338.       FREE (font->kern_pairs[i].name1);
  339.       FREE (font->kern_pairs[i].name2);
  340.     }
  341.   FREE (font->kern_pairs);
  342.   
  343.   /* Track kern. */
  344.   FREE (font->track_kerns);
  345.  
  346.   /* Private data. */
  347.   strhash_free (font->private->fontnames);
  348.   strhash_free (font->private->compositenames);
  349.  
  350.   free (font);
  351.  
  352.   return AFM_SUCCESS;
  353. }
  354.  
  355.  
  356. #define STR(str) (str ? str : "")
  357. #define BOOL(val) (val ? "true" : "false")
  358. void
  359. afm_font_dump (FILE *fp, AFMFont font)
  360. {
  361.   int i;
  362.  
  363.   fprintf (fp, "AFM Format Specification version: %g\n", font->version);
  364.   fprintf (fp, "Global Font Information\n");
  365.   fprintf (fp, "  FontName:\t%s\n",     STR (font->global_info.FontName));
  366.   fprintf (fp, "  FullName:\t%s\n",     STR (font->global_info.FullName));
  367.   fprintf (fp, "  FamilyName:\t%s\n",     STR (font->global_info.FamilyName));
  368.   fprintf (fp, "  Weight:\t%s\n",     STR (font->global_info.Weight));
  369.   fprintf (fp, "  FontBBox:\t%g %g %g %g\n",
  370.        font->global_info.FontBBox_llx, font->global_info.FontBBox_lly,
  371.        font->global_info.FontBBox_urx, font->global_info.FontBBox_ury);
  372.   fprintf (fp, "  Version:\t%s\n",     STR (font->global_info.Version));
  373.   fprintf (fp, "  Notice:\t%s\n",     STR (font->global_info.Notice));
  374.   fprintf (fp, "  EncodingScheme:\t%s\n",
  375.        STR (font->global_info.EncodingScheme));
  376.   fprintf (fp, "  MappingScheme:\t%ld\n", font->global_info.MappingScheme);
  377.   fprintf (fp, "  EscChar:\t%ld\n", font->global_info.EscChar);
  378.   fprintf (fp, "  CharacterSet:\t%s\n", STR (font->global_info.CharacterSet));
  379.   fprintf (fp, "  Characters:\t%ld\n",     font->global_info.Characters);
  380.   fprintf (fp, "  IsBaseFont:\t%s\n",     BOOL(font->global_info.IsBaseFont));
  381.   fprintf (fp, "  VVector:\t%g %g\n",
  382.        font->global_info.VVector_0,    font->global_info.VVector_1);
  383.   fprintf (fp, "  IsFixedV:\t%s\n",     BOOL(font->global_info.IsFixedV));
  384.   fprintf (fp, "  CapHeight:\t%g\n",     font->global_info.CapHeight);
  385.   fprintf (fp, "  XHeight:\t%g\n",     font->global_info.XHeight);
  386.   fprintf (fp, "  Ascender:\t%g\n",     font->global_info.Ascender);
  387.   fprintf (fp, "  Descender:\t%g\n",     font->global_info.Descender);
  388.  
  389.   for (i = 0; i < 2; i++)
  390.     if (font->writing_direction_metrics[i].is_valid)
  391.       {
  392.     fprintf (fp, "Writing Direction %d\n", i);
  393.     fprintf (fp, "  UnderlinePosition: %g\n",
  394.          font->writing_direction_metrics[i].UnderlinePosition);
  395.     fprintf (fp, "  UnderlineThickness: %g\n",
  396.          font->writing_direction_metrics[i].UnderlineThickness);
  397.     fprintf (fp, "  ItalicAngle: %g\n",
  398.          font->writing_direction_metrics[i].ItalicAngle);
  399.     fprintf (fp, "  CharWidth: %g %g\n",
  400.          font->writing_direction_metrics[i].CharWidth_x,
  401.          font->writing_direction_metrics[i].CharWidth_y);
  402.     fprintf (fp, "  IsFixedPitch: %s\n",
  403.          BOOL (font->writing_direction_metrics[i].IsFixedPitch));
  404.       }
  405.  
  406.   /* Individual Character Metrics. */
  407.   fprintf (fp, "Individual Character Metrics %ld\n",
  408.        font->num_character_metrics);
  409.   for (i = 0; i < font->num_character_metrics; i++)
  410.     {
  411.       AFMIndividualCharacterMetrics *cm;
  412.       cm = &font->character_metrics[i];
  413.  
  414.       fprintf (fp, "  C %ld ; N %s ; B %g %g %g %g\n",
  415.            cm->character_code, STR (cm->name), 
  416.            cm->llx, cm->lly, cm->urx, cm->ury);
  417.       fprintf (fp,
  418.            "    W0X %g ; W0Y %g ; W1X %g ; W1Y %g ; VV %g %g\n",
  419.            cm->w0x, cm->w0y, cm->w1x, cm->w1y, cm->vv_x, cm->vv_y);
  420.     }
  421.  
  422.   /* Composite Character Data. */
  423.   fprintf (fp, "Composite Character Data %ld\n", font->num_composites);
  424.   for (i = 0; i < font->num_composites; i++)
  425.     {
  426.       AFMComposite *cm;
  427.       int j;
  428.  
  429.       cm = &font->composites[i];
  430.  
  431.       fprintf (fp, "  CC %s %ld", cm->name, cm->num_components);
  432.       for (j = 0; j < cm->num_components; j++)
  433.     fprintf (fp, " ; PCC %s %g %g",
  434.          cm->components[j].name,
  435.          cm->components[j].deltax,
  436.          cm->components[j].deltay);
  437.       fprintf (fp, "\n");
  438.     }
  439.  
  440.   /* Kern pairs. */
  441.   fprintf (fp, "Pair-Wise Kerning %ld\n", font->num_kern_pairs);
  442.   for (i = 0; i < font->num_kern_pairs; i++)
  443.     {
  444.       AFMPairWiseKerning *kp;
  445.       kp = &font->kern_pairs[i];
  446.  
  447.       fprintf (fp, "  KP %s %s %g %g\n", STR (kp->name1), STR (kp->name2),
  448.            kp->kx, kp->ky);
  449.     }
  450.  
  451.   fprintf (fp, "Track Kerning %ld\n", font->num_track_kerns);
  452.   for (i = 0; i < font->num_track_kerns; i++)
  453.     {
  454.       AFMTrackKern *tk;
  455.       tk = &font->track_kerns[i];
  456.  
  457.       fprintf (fp, "  TrackKern %ld %g %g %g %g\n", tk->degree,
  458.            tk->min_ptsize, tk->min_kern,
  459.            tk->max_ptsize, tk->max_kern);
  460.     }
  461. }
  462.  
  463.  
  464. AFMError
  465. afm_font_stringwidth (AFMFont font, AFMNumber ptsize, char *string,
  466.               unsigned int stringlen, AFMNumber *w0x_return,
  467.               AFMNumber *w0y_return)
  468. {
  469.   unsigned int i;
  470.   AFMNumber x = 0.0;
  471.   AFMNumber y = 0.0;
  472.   AFMIndividualCharacterMetrics *cm;
  473.  
  474.   if (!font || !string || !font->writing_direction_metrics[0].is_valid)
  475.     return AFM_ERROR_ARGUMENT;
  476.  
  477.   /* Check shortcut. */
  478.   if (font->writing_direction_metrics[0].IsFixedPitch)
  479.     {
  480.       /* This is the easy case. */
  481.       x = stringlen * font->writing_direction_metrics[0].CharWidth_x;
  482.       y = stringlen * font->writing_direction_metrics[0].CharWidth_y;
  483.     }
  484.   else
  485.     {
  486.       /* Count character by character. */
  487.       for (i = 0; i < stringlen; i++)
  488.     {
  489.       cm = font->encoding[(unsigned int) string[i]];
  490.       if (cm == AFM_ENC_NONE || cm == AFM_ENC_NON_EXISTENT)
  491.         {
  492.           /* Use the undef font. */
  493.           x += font->private->undef->w0x;
  494.           y += font->private->undef->w0y;
  495.         }
  496.       else
  497.         {
  498.           /* Font found and valid, take values. */
  499.           x += cm->w0x;
  500.           y += cm->w0y;
  501.         }
  502.     }
  503.     }
  504.   
  505.   *w0x_return = x / UNITS_PER_POINT * ptsize;
  506.   *w0y_return = y / UNITS_PER_POINT * ptsize;
  507.  
  508.   return AFM_SUCCESS;
  509. }
  510.  
  511.  
  512. AFMError
  513. afm_font_charwidth (AFMFont font, AFMNumber ptsize, unsigned int ch,
  514.             AFMNumber *w0x_return, AFMNumber *w0y_return)
  515. {
  516.   AFMNumber x = 0.0;
  517.   AFMNumber y = 0.0;
  518.   AFMIndividualCharacterMetrics *cm;
  519.   
  520.   if (!font || !font->writing_direction_metrics[0].is_valid)
  521.     return AFM_ERROR_ARGUMENT;
  522.  
  523.   /* Check shortcut. */
  524.   if (font->writing_direction_metrics[0].IsFixedPitch)
  525.     {
  526.       x = font->writing_direction_metrics[0].CharWidth_x;
  527.       y = font->writing_direction_metrics[0].CharWidth_y;
  528.     }
  529.   else
  530.     {
  531.       cm = font->encoding[(unsigned int) ch];
  532.       if (cm == AFM_ENC_NONE || cm == AFM_ENC_NON_EXISTENT)
  533.     {
  534.       /* Use the undef font. */
  535.       x = font->private->undef->w0x;
  536.       y = font->private->undef->w0y;
  537.     }
  538.       else
  539.     {
  540.       /* Font found and valid, take values. */
  541.       x = cm->w0x;
  542.       y = cm->w0y;
  543.     }
  544.     }
  545.  
  546.   *w0x_return = x / UNITS_PER_POINT * ptsize;
  547.   *w0y_return = y / UNITS_PER_POINT * ptsize;
  548.  
  549.   return AFM_SUCCESS;
  550. }
  551.  
  552.  
  553. AFMError
  554. afm_font_encode (AFMFont font, unsigned char code, char *name,
  555.          unsigned int flags)
  556. {
  557.   AFMIndividualCharacterMetrics *cm;
  558.   AFMComposite *comp;
  559.  
  560.   if (font == NULL)
  561.     return AFM_ERROR_ARGUMENT;
  562.  
  563.   if (name)
  564.     {
  565.       /* Get font. */
  566.       if (!strhash_get (font->private->fontnames, name, strlen (name),
  567.             (void *) &cm))
  568.     {
  569.       /* Check composite characters. */
  570.       if ((flags & AFM_ENCODE_ACCEPT_COMPOSITES) == 0
  571.           || strhash_get (font->private->compositenames, name,
  572.                   strlen (name), (void *) &comp) == 0)
  573.         cm = AFM_ENC_NON_EXISTENT;
  574.       else
  575.         {
  576.           /*
  577.            * Ok, composite character found, now find the character
  578.            * specified by the first composite component.
  579.            */
  580.           if (!strhash_get (font->private->fontnames,
  581.                 comp->components[0].name,
  582.                 strlen (comp->components[0].name),
  583.                 (void *) &cm))
  584.         cm = AFM_ENC_NON_EXISTENT;
  585.         }
  586.     }
  587.     }
  588.   else
  589.     cm = AFM_ENC_NONE;
  590.  
  591.   font->encoding[(unsigned int) code] = cm;
  592.  
  593.   return AFM_SUCCESS;
  594. }
  595.  
  596.  
  597. AFMError
  598. afm_font_encoding (AFMFont font, AFMEncoding enc, unsigned int flags)
  599. {
  600.   int i;
  601.   AFMIndividualCharacterMetrics *cm;
  602.  
  603.   if (font == NULL)
  604.     return AFM_ERROR_ARGUMENT;
  605.  
  606.   switch (enc)
  607.     {
  608.     case AFM_ENCODING_DEFAULT:
  609.       /* Clear encoding. */
  610.       for (i = 0; i < 256; i++)
  611.     font->encoding[i] = AFM_ENC_NONE;
  612.  
  613.       /* Apply font's default encoding. */
  614.       for (i = 0; i < font->num_character_metrics; i++)
  615.     {
  616.       cm = &font->character_metrics[i];
  617.       font->encoding[cm->character_code] = cm;
  618.     }
  619.       break;
  620.  
  621.     case AFM_ENCODING_LATIN1:
  622.       apply_encoding (font, afm_latin1_encoding, flags);
  623.       break;
  624.  
  625.     case AFM_ENCODING_LATIN2:
  626.       apply_encoding (font, afm_latin2_encoding, flags);
  627.       break;
  628.  
  629.     case AFM_ENCODING_LATIN3:
  630.       apply_encoding (font, afm_latin3_encoding, flags);
  631.       break;
  632.  
  633.     case AFM_ENCODING_IBMPC:
  634.       apply_encoding (font, afm_ibmpc_encoding, flags);
  635.       break;
  636.  
  637.     case AFM_ENCODING_ASCII:
  638.       /*
  639.        * First apply one encoding (all have equal first 128 characters),
  640.        * then zap last 128 chars.
  641.        */
  642.       apply_encoding (font, afm_latin1_encoding, flags);
  643.       for (i = 128; i < 256; i++)
  644.     font->encoding[i] = AFM_ENC_NONE;
  645.       break;
  646.  
  647.     case AFM_ENCODING_MAC:
  648.       apply_encoding (font, afm_mac_encoding, flags);
  649.       break;
  650.  
  651.     case AFM_ENCODING_VMS:
  652.       apply_encoding (font, afm_vms_encoding, flags);
  653.       break;
  654.  
  655.     case AFM_ENCODING_HP8:
  656.       apply_encoding (font, afm_hp8_encoding, flags);
  657.       break;
  658.     }
  659.  
  660.   return AFM_SUCCESS;
  661. }
  662.  
  663.  
  664. /*
  665.  * Internal help functions.
  666.  */
  667.  
  668.  
  669. void
  670. #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
  671.   afm_message (AFMHandle handle, int level, char *fmt, ...)
  672. #else
  673.   afm_message (handle, level, va_alist)
  674.      AFMHandle handle;
  675.      int level;
  676.      va_dcl
  677. #endif
  678. {
  679.   va_list args;
  680. #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
  681.   va_start(args, fmt);
  682. #else
  683.   char *fmt;
  684.  
  685.   va_start(args);
  686.   fmt = va_arg(args, char *);
  687. #endif
  688.  
  689.   if (handle->verbose < level)
  690.     return;
  691.  
  692. #ifdef HAVE_VPRINTF
  693.   vfprintf (stderr, fmt, args);
  694. #else
  695.   _doprnt(fmt, args, stderr);
  696. #endif
  697.   va_end (args);
  698. }
  699.  
  700.  
  701. void
  702. #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
  703.   afm_error (AFMHandle handle, char *fmt, ...)
  704. #else
  705.   afm_error (handle, va_alist)
  706.      AFMHandle handle;
  707.      va_dcl
  708. #endif
  709. {
  710.   va_list args;
  711. #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
  712.   va_start(args, fmt);
  713. #else
  714.   char *fmt;
  715.  
  716.   va_start(args);
  717.   fmt = va_arg(args, char *);
  718. #endif
  719.  
  720.   fprintf (stderr, "AFM Error: ");
  721.  
  722. #ifdef HAVE_VPRINTF
  723.   vfprintf (stderr, fmt, args);
  724. #else
  725.    _doprnt(fmt, args, stderr);
  726. #endif
  727.  
  728.   va_end (args);
  729.   fprintf (stderr, "\n");
  730. }
  731.  
  732.  
  733. /*
  734.  * Static functions.
  735.  */
  736.  
  737. static void
  738. read_font_map (AFMHandle handle, char *name)
  739. {
  740.   FILE *fp;
  741.   char buf[512];
  742.   char fullname[512];
  743.   unsigned int dirlen;
  744.   char *cp, *cp2;
  745.  
  746.   afm_message (handle, 1, "AFM: reading font map \"%s\"\n", name);
  747.  
  748.   fp = fopen (name, "r");
  749.   if (fp == NULL)
  750.     {
  751.       afm_message (handle, 1, "AFM: couldn't open font map \"%s\": %s\n",
  752.            name, strerror (errno));
  753.       return;
  754.     }
  755.  
  756.   /* Get directory */
  757.   cp = strrchr (name, '/');
  758.   if (cp)
  759.     {
  760.       dirlen = cp - name + 1;
  761.       memcpy (fullname, name, dirlen);
  762.     }
  763.   else
  764.     {
  765.       dirlen = 2;
  766.       memcpy (fullname, "./", dirlen);
  767.     }
  768.  
  769.   while (fgets (buf, sizeof (buf), fp))
  770.     {
  771.       char font[256];
  772.       char file[256];
  773.  
  774.       if (sscanf (buf, "%s %s", font, file) != 2)
  775.     {
  776.       afm_error (handle, "malformed line in font map \"%s\":\n%s",
  777.              name, buf);
  778.       continue;
  779.     }
  780.       
  781.       /* Do we already have this font? */
  782.       if (strhash_get (handle->font_map, font, strlen (font), (void *) &cp))
  783.     continue;
  784.  
  785.       /* Append file name. */
  786.       strcpy (fullname + dirlen, file);
  787.       cp = (char *) malloc (strlen (fullname) + 1);
  788.       if (cp == NULL)
  789.     {
  790.       afm_error (handle, "couldn't add font: out of memory");
  791.       goto out;
  792.     }
  793.       strcpy (cp, fullname);
  794.  
  795.       afm_message (handle, 2, "AFM: font mapping: %s -> %s\n", font, cp);
  796.       (void) strhash_put (handle->font_map, font, strlen (font), cp,
  797.               (void *) &cp2);
  798.     }
  799.  
  800.  out:
  801.   fclose (fp);
  802. }
  803.  
  804.  
  805. static void
  806. apply_encoding (AFMFont font, AFMEncodingTable *enc, unsigned int flags)
  807. {
  808.   int i;
  809.   AFMIndividualCharacterMetrics *cm;
  810.   AFMComposite *comp;
  811.  
  812.   for (i = 0; enc[i].code >= 0; i++)
  813.     {
  814.       if (enc[i].character == AFM_ENC_NONE)
  815.     font->encoding[enc[i].code] = AFM_ENC_NONE;
  816.       else if (enc[i].character == AFM_ENC_NON_EXISTENT)
  817.     font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
  818.       else
  819.     {
  820.       if (strhash_get (font->private->fontnames, enc[i].character,
  821.                strlen (enc[i].character), (void *) &cm))
  822.         font->encoding[enc[i].code] = cm;
  823.       else
  824.         {
  825.           /* Check composite characters. */
  826.           if ((flags & AFM_ENCODE_ACCEPT_COMPOSITES) == 0
  827.           || strhash_get (font->private->compositenames,
  828.                   enc[i].character, strlen (enc[i].character),
  829.                   (void *) &comp) == 0)
  830.         font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
  831.           else
  832.         {
  833.           /* Composite character found. */
  834.           if (strhash_get (font->private->fontnames,
  835.                    comp->components[0].name,
  836.                    strlen (comp->components[0].name),
  837.                    (void *) &cm))
  838.             font->encoding[enc[i].code] = cm;
  839.           else
  840.             font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
  841.         }
  842.         }
  843.     }
  844.     }
  845. }
  846.